{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pL--_KGdYoBz"
   },
   "source": [
    "##### Copyright 2019 The TensorFlow Authors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "cellView": "form",
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:45.549235Z",
     "iopub.status.busy": "2023-11-07T23:58:45.548946Z",
     "iopub.status.idle": "2023-11-07T23:58:45.553601Z",
     "shell.execute_reply": "2023-11-07T23:58:45.552891Z"
    },
    "id": "uBDvXpYzYnGj"
   },
   "outputs": [],
   "source": [
    "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HQzaEQuJiW_d"
   },
   "source": [
    "# TFRecord 和 tf.Example\n",
    "\n",
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td><a target=\"_blank\" href=\"https://tensorflow.google.cn/tutorials/load_data/tfrecord\"><img src=\"https://tensorflow.google.cn/images/tf_logo_32px.png\">在 TensorFlow.org 上查看 </a></td>\n",
    "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/zh-cn/tutorials/load_data/tfrecord.ipynb\"><img src=\"https://tensorflow.google.cn/images/colab_logo_32px.png\">在 Google Colab 中运行</a></td>\n",
    "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/zh-cn/tutorials/load_data/tfrecord.ipynb\"><img src=\"https://tensorflow.google.cn/images/GitHub-Mark-32px.png\">在  GitHub 上查看源代码</a></td>\n",
    "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/zh-cn/tutorials/load_data/tfrecord.ipynb\"><img src=\"https://tensorflow.google.cn/images/download_logo_32px.png\">下载笔记本</a></td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3pkUd_9IZCFO"
   },
   "source": [
    "TFRecord 格式是一种用于存储二进制记录序列的简单格式。\n",
    "\n",
    "[协议缓冲区](https://developers.google.com/protocol-buffers/)是一个跨平台、跨语言的库，用于高效地序列化结构化数据。\n",
    "\n",
    "协议消息由 `.proto` 文件定义，这通常是了解消息类型最简单的方法。\n",
    "\n",
    "`tf.train.Example` 消息（或 protobuf）是一种灵活的消息类型，表示 `{\"string\": value}` 映射。它可以与 TensorFlow 结合使用，并在 [TFX](https://tensorflow.google.cn/tfx/) 等更高级 API 中使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Ac83J0QxjhFt"
   },
   "source": [
    "此笔记本将演示如何创建、解析和使用 `tf.Example` 消息，以及如何在 `.tfrecord` 文件之间对 `tf.Example` 消息进行序列化、写入和读取。\n",
    "\n",
    "注：这些结构虽然有用，但并不是强制的。您无需转换现有代码即可使用 TFRecord，除非您正在[使用 tf.data](https://tensorflow.google.cn/guide/data) 且读取数据仍是训练的瓶颈。有关数据集性能的提示，请参阅[使用 tf.data API 提升性能](https://tensorflow.google.cn/guide/data_performance)。\n",
    "\n",
    "注：通常，您应当将数据分片到多个文件，以便可以并行化 I/O（在单个主机内或跨多个主机）。根据经验法则，文件数量至少应达到读取数据的主机数量的 10 倍。同时，每个文件都应当足够大（至少 10+MB，理想情况下为 100MB+），以便您从 I/O 预提取中受益。例如，假设您有 `X` GB 数据，并且您计划在最多 `N` 个主机上进行训练。理想情况下，您应当将数据分片到 ~`10*N` 个文件，只要 ~`X/(10*N)` 为 10+ MB（理想情况下为 100+ MB）。如果小于该值，则可能需要创建更少的分片来权衡并行性优势和 I/O 预提取优势。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WkRreBf1eDVc"
   },
   "source": [
    "## 设置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:45.557807Z",
     "iopub.status.busy": "2023-11-07T23:58:45.557541Z",
     "iopub.status.idle": "2023-11-07T23:58:48.253883Z",
     "shell.execute_reply": "2023-11-07T23:58:48.252997Z"
    },
    "id": "Ja7sezsmnXph"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-11-07 23:58:46.036021: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:9261] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
      "2023-11-07 23:58:46.036079: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:607] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
      "2023-11-07 23:58:46.037872: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1515] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "import numpy as np\n",
    "import IPython.display as display"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "e5Kq88ccUWQV"
   },
   "source": [
    "## `tf.train.Example`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "VrdQHgvNijTi"
   },
   "source": [
    "### `tf.Example` 的数据类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "lZw57Qrn4CTE"
   },
   "source": [
    "从根本上讲，`tf.Example` 是 `{\"string\": tf.train.Feature}` 映射。\n",
    "\n",
    "`tf.train.Feature` 消息类型可以接受以下三种类型（请参阅 [`.proto` 文件](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/example/feature.proto)）。大多数其他通用类型也可以强制转换成下面的其中一种：\n",
    "\n",
    "1. `tf.train.BytesList`（可强制转换自以下类型）\n",
    "\n",
    "- `string`\n",
    "- `byte`\n",
    "\n",
    "1. `tf.train.FloatList`（可强制转换自以下类型）\n",
    "\n",
    "- `float` (`float32`)\n",
    "- `double` (`float64`)\n",
    "\n",
    "1. `tf.train.Int64List`（可强制转换自以下类型）\n",
    "\n",
    "- `bool`\n",
    "- `enum`\n",
    "- `int32`\n",
    "- `uint32`\n",
    "- `int64`\n",
    "- `uint64`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_e3g9ExathXP"
   },
   "source": [
    "为了将标准 TensorFlow 类型转换为兼容 `tf.Example` 的 `tf.train.Feature`，可以使用下面的快捷函数。请注意，每个函数会接受标量输入值并返回包含上述三种 `list` 类型之一的 `tf.train.Feature`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:48.258999Z",
     "iopub.status.busy": "2023-11-07T23:58:48.258247Z",
     "iopub.status.idle": "2023-11-07T23:58:48.264498Z",
     "shell.execute_reply": "2023-11-07T23:58:48.263794Z"
    },
    "id": "mbsPOUpVtYxA"
   },
   "outputs": [],
   "source": [
    "# The following functions can be used to convert a value to a type compatible\n",
    "# with tf.train.Example.\n",
    "\n",
    "def _bytes_feature(value):\n",
    "  \"\"\"Returns a bytes_list from a string / byte.\"\"\"\n",
    "  if isinstance(value, type(tf.constant(0))):\n",
    "    value = value.numpy() # BytesList won't unpack a string from an EagerTensor.\n",
    "  return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))\n",
    "\n",
    "def _float_feature(value):\n",
    "  \"\"\"Returns a float_list from a float / double.\"\"\"\n",
    "  return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))\n",
    "\n",
    "def _int64_feature(value):\n",
    "  \"\"\"Returns an int64_list from a bool / enum / int / uint.\"\"\"\n",
    "  return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Wst0v9O8hgzy"
   },
   "source": [
    "注：为了简单起见，本示例仅使用标量输入。要处理非标量特征，最简单的方法是使用 `tf.io.serialize_tensor` 将张量转换为二进制字符串。在 TensorFlow 中，字符串是标量。使用 `tf.io.parse_tensor` 可将二进制字符串转换回张量。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "vsMbkkC8xxtB"
   },
   "source": [
    "下面是有关这些函数如何工作的一些示例。请注意不同的输入类型和标准化的输出类型。如果函数的输入类型与上述可强制转换的类型均不匹配，则该函数将引发异常（例如，`_int64_feature(1.0)` 将出错，因为 `1.0` 是浮点数，应该用于 `_float_feature` 函数）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:48.268108Z",
     "iopub.status.busy": "2023-11-07T23:58:48.267588Z",
     "iopub.status.idle": "2023-11-07T23:58:50.564264Z",
     "shell.execute_reply": "2023-11-07T23:58:50.563484Z"
    },
    "id": "hZzyLGr0u73y"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "bytes_list {\n",
      "  value: \"test_string\"\n",
      "}\n",
      "\n",
      "bytes_list {\n",
      "  value: \"test_bytes\"\n",
      "}\n",
      "\n",
      "float_list {\n",
      "  value: 2.7182817459106445\n",
      "}\n",
      "\n",
      "int64_list {\n",
      "  value: 1\n",
      "}\n",
      "\n",
      "int64_list {\n",
      "  value: 1\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(_bytes_feature(b'test_string'))\n",
    "print(_bytes_feature(u'test_bytes'.encode('utf-8')))\n",
    "\n",
    "print(_float_feature(np.exp(1)))\n",
    "\n",
    "print(_int64_feature(True))\n",
    "print(_int64_feature(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "nj1qpfQU5qmi"
   },
   "source": [
    "可以使用 `.SerializeToString` 方法将所有协议消息序列化为二进制字符串："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.568513Z",
     "iopub.status.busy": "2023-11-07T23:58:50.567832Z",
     "iopub.status.idle": "2023-11-07T23:58:50.575410Z",
     "shell.execute_reply": "2023-11-07T23:58:50.574672Z"
    },
    "id": "5afZkORT5pjm"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\x12\\x06\\n\\x04T\\xf8-@'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature = _float_feature(np.exp(1))\n",
    "\n",
    "feature.SerializeToString()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "laKnw9F3hL-W"
   },
   "source": [
    "### 创建 `tf.Example` 消息"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "b_MEnhxchQPC"
   },
   "source": [
    "假设您要根据现有数据创建 `tf.Example` 消息。在实践中，数据集可能来自任何地方，但是从单个观测值创建 `tf.Example` 消息的过程相同：\n",
    "\n",
    "1. 在每个观测结果中，需要使用上述其中一种函数，将每个值转换为包含三种兼容类型之一的 `tf.train.Feature`。\n",
    "\n",
    "2. 创建一个从特征名称字符串到第 1 步中生成的编码特征值的映射（字典）。\n",
    "\n",
    "3. 将第 2 步中生成的映射转换为 [`Features` 消息](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/example/feature.proto#L85)。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4EgFQ2uHtchc"
   },
   "source": [
    "在此笔记本中，您将使用 NumPy 创建一个数据集。\n",
    "\n",
    "此数据集将具有 4 个特征：\n",
    "\n",
    "- 具有相等 `False` 或 `True` 概率的布尔特征\n",
    "- 从 `[0, 5]` 均匀随机选择的整数特征\n",
    "- 通过将整数特征作为索引从字符串表生成的字符串特征\n",
    "- 来自标准正态分布的浮点特征\n",
    "\n",
    "请思考一个样本，其中包含来自上述每个分布的 10,000 个独立且分布相同的观测值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.579521Z",
     "iopub.status.busy": "2023-11-07T23:58:50.578903Z",
     "iopub.status.idle": "2023-11-07T23:58:50.584262Z",
     "shell.execute_reply": "2023-11-07T23:58:50.583605Z"
    },
    "id": "CnrguFAy3YQv"
   },
   "outputs": [],
   "source": [
    "# The number of observations in the dataset.\n",
    "n_observations = int(1e4)\n",
    "\n",
    "# Boolean feature, encoded as False or True.\n",
    "feature0 = np.random.choice([False, True], n_observations)\n",
    "\n",
    "# Integer feature, random from 0 to 4.\n",
    "feature1 = np.random.randint(0, 5, n_observations)\n",
    "\n",
    "# String feature.\n",
    "strings = np.array([b'cat', b'dog', b'chicken', b'horse', b'goat'])\n",
    "feature2 = strings[feature1]\n",
    "\n",
    "# Float feature, from a standard normal distribution.\n",
    "feature3 = np.random.randn(n_observations)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "aGrscehJr7Jd"
   },
   "source": [
    "您可以使用 `_bytes_feature`、`_float_feature` 或 `_int64_feature` 将下面的每个特征强制转换为兼容 `tf.Example` 的类型。然后，可以通过下面的已编码特征创建 `tf.Example` 消息："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.587833Z",
     "iopub.status.busy": "2023-11-07T23:58:50.587299Z",
     "iopub.status.idle": "2023-11-07T23:58:50.591970Z",
     "shell.execute_reply": "2023-11-07T23:58:50.591260Z"
    },
    "id": "RTCS49Ij_kUw"
   },
   "outputs": [],
   "source": [
    "def serialize_example(feature0, feature1, feature2, feature3):\n",
    "  \"\"\"\n",
    "  Creates a tf.train.Example message ready to be written to a file.\n",
    "  \"\"\"\n",
    "  # Create a dictionary mapping the feature name to the tf.train.Example-compatible\n",
    "  # data type.\n",
    "  feature = {\n",
    "      'feature0': _int64_feature(feature0),\n",
    "      'feature1': _int64_feature(feature1),\n",
    "      'feature2': _bytes_feature(feature2),\n",
    "      'feature3': _float_feature(feature3),\n",
    "  }\n",
    "\n",
    "  # Create a Features message using tf.train.Example.\n",
    "\n",
    "  example_proto = tf.train.Example(features=tf.train.Features(feature=feature))\n",
    "  return example_proto.SerializeToString()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "XftzX9CN_uGT"
   },
   "source": [
    "例如，假设您从数据集中获得了一个观测值 `[False, 4, bytes('goat'), 0.9876]`。您可以使用 `create_message()` 创建和打印此观测值的 `tf.Example` 消息。如上所述，每个观测值将被写为一条 `Features` 消息。请注意，`tf.Example` [消息](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/example/example.proto#L88)只是 `Features` 消息外围的包装器："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.595538Z",
     "iopub.status.busy": "2023-11-07T23:58:50.594961Z",
     "iopub.status.idle": "2023-11-07T23:58:50.599925Z",
     "shell.execute_reply": "2023-11-07T23:58:50.599280Z"
    },
    "id": "N8BtSx2RjYcb"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\nR\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04[\\xd3|?\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x04\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x14\\n\\x08feature2\\x12\\x08\\n\\x06\\n\\x04goat'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# This is an example observation from the dataset.\n",
    "\n",
    "example_observation = []\n",
    "\n",
    "serialized_example = serialize_example(False, 4, b'goat', 0.9876)\n",
    "serialized_example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_pbGATlG6u-4"
   },
   "source": [
    "要解码消息，请使用 `tf.train.Example.FromString` 方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.603302Z",
     "iopub.status.busy": "2023-11-07T23:58:50.602920Z",
     "iopub.status.idle": "2023-11-07T23:58:50.607700Z",
     "shell.execute_reply": "2023-11-07T23:58:50.607063Z"
    },
    "id": "dGim-mEm6vit"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "features {\n",
       "  feature {\n",
       "    key: \"feature0\"\n",
       "    value {\n",
       "      int64_list {\n",
       "        value: 0\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "  feature {\n",
       "    key: \"feature1\"\n",
       "    value {\n",
       "      int64_list {\n",
       "        value: 4\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "  feature {\n",
       "    key: \"feature2\"\n",
       "    value {\n",
       "      bytes_list {\n",
       "        value: \"goat\"\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "  feature {\n",
       "    key: \"feature3\"\n",
       "    value {\n",
       "      float_list {\n",
       "        value: 0.9876000285148621\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "example_proto = tf.train.Example.FromString(serialized_example)\n",
    "example_proto"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "o6qxofy89obI"
   },
   "source": [
    "## TFRecords 格式详细信息\n",
    "\n",
    "TFRecord 文件包含一系列记录。该文件只能按顺序读取。\n",
    "\n",
    "每条记录包含一个字节字符串（用于数据有效负载），外加数据长度，以及用于完整性检查的 CRC32C（使用 Castagnoli 多项式的 32 位 CRC）哈希值。\n",
    "\n",
    "每条记录会存储为以下格式：\n",
    "\n",
    "```\n",
    "uint64 length\n",
    "uint32 masked_crc32_of_length\n",
    "byte   data[length]\n",
    "uint32 masked_crc32_of_data\n",
    "```\n",
    "\n",
    "将记录连接起来以生成文件。[此处](https://en.wikipedia.org/wiki/Cyclic_redundancy_check)对 CRC 进行了说明，且 CRC 的掩码为：\n",
    "\n",
    "```\n",
    "masked_crc = ((crc &gt;&gt; 15) | (crc &lt;&lt; 17)) + 0xa282ead8ul\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "-0iHagLQCJv6"
   },
   "source": [
    "注：没有要求在 TFRecord 文件中使用 `tf.train.Example`。`tf.train.Example` 只是一种将字典序列化为字节串的方法。任何可以在 TensorFlow 中解码的字节串都可以存储在 TFRecord 文件中。示例包括：文本行、JSON（使用 `tf.io.decode_json_example`）、编码图像数据或序列化 `tf.Tensors`（使用 `tf.io.serialize_tensor`/`tf.io.parse_tensor`）。请参阅 `tf.io` 模块了解更多选项。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "y-Hjmee-fbLH"
   },
   "source": [
    "## 使用 `tf.data` 的 TFRecord 文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "GmehkCCT81Ez"
   },
   "source": [
    "`tf.data` 模块还提供用于在 TensorFlow 中读取和写入数据的工具。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1FISEuz8ubu3"
   },
   "source": [
    "### 写入 TFRecord 文件\n",
    "\n",
    "要将数据放入数据集中，最简单的方式是使用 `from_tensor_slices` 方法。\n",
    "\n",
    "若应用于数组，将返回标量数据集："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.611529Z",
     "iopub.status.busy": "2023-11-07T23:58:50.611207Z",
     "iopub.status.idle": "2023-11-07T23:58:50.620658Z",
     "shell.execute_reply": "2023-11-07T23:58:50.620012Z"
    },
    "id": "mXeaukvwu5_-"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<_TensorSliceDataset element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.data.Dataset.from_tensor_slices(feature1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "f-q0VKyZvcad"
   },
   "source": [
    "若应用于数组的元组，将返回元组的数据集："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.624104Z",
     "iopub.status.busy": "2023-11-07T23:58:50.623635Z",
     "iopub.status.idle": "2023-11-07T23:58:50.635813Z",
     "shell.execute_reply": "2023-11-07T23:58:50.635163Z"
    },
    "id": "H5sWyu1kxnvg"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<_TensorSliceDataset element_spec=(TensorSpec(shape=(), dtype=tf.bool, name=None), TensorSpec(shape=(), dtype=tf.int64, name=None), TensorSpec(shape=(), dtype=tf.string, name=None), TensorSpec(shape=(), dtype=tf.float64, name=None))>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "features_dataset = tf.data.Dataset.from_tensor_slices((feature0, feature1, feature2, feature3))\n",
    "features_dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.639148Z",
     "iopub.status.busy": "2023-11-07T23:58:50.638562Z",
     "iopub.status.idle": "2023-11-07T23:58:50.655779Z",
     "shell.execute_reply": "2023-11-07T23:58:50.655044Z"
    },
    "id": "m1C-t71Nywze"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(False, shape=(), dtype=bool)\n",
      "tf.Tensor(1, shape=(), dtype=int64)\n",
      "tf.Tensor(b'dog', shape=(), dtype=string)\n",
      "tf.Tensor(0.726594013313797, shape=(), dtype=float64)\n"
     ]
    }
   ],
   "source": [
    "# Use `take(1)` to only pull one example from the dataset.\n",
    "for f0,f1,f2,f3 in features_dataset.take(1):\n",
    "  print(f0)\n",
    "  print(f1)\n",
    "  print(f2)\n",
    "  print(f3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "mhIe63awyZYd"
   },
   "source": [
    "使用 `tf.data.Dataset.map` 方法可将函数应用于 `Dataset` 的每个元素。\n",
    "\n",
    "映射函数必须在 TensorFlow 计算图模式下进行运算（它必须在 `tf.Tensors` 上运算并返回）。可以使用 `tf.py_function` 包装非张量函数（如 `serialize_example`）以使其兼容。\n",
    "\n",
    "使用 `tf.py_function` 需要指定形状和类型信息，否则它将不可用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.659824Z",
     "iopub.status.busy": "2023-11-07T23:58:50.659114Z",
     "iopub.status.idle": "2023-11-07T23:58:50.663415Z",
     "shell.execute_reply": "2023-11-07T23:58:50.662729Z"
    },
    "id": "apB5KYrJzjPI"
   },
   "outputs": [],
   "source": [
    "def tf_serialize_example(f0,f1,f2,f3):\n",
    "  tf_string = tf.py_function(\n",
    "    serialize_example,\n",
    "    (f0, f1, f2, f3),  # Pass these args to the above function.\n",
    "    tf.string)      # The return type is `tf.string`.\n",
    "  return tf.reshape(tf_string, ()) # The result is a scalar."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.666891Z",
     "iopub.status.busy": "2023-11-07T23:58:50.666253Z",
     "iopub.status.idle": "2023-11-07T23:58:50.677668Z",
     "shell.execute_reply": "2023-11-07T23:58:50.676908Z"
    },
    "id": "lHFjW4u4Npz9"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nQ\\n\\x13\\n\\x08feature2\\x12\\x07\\n\\x05\\n\\x03dog\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x01\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\x11\\x02:?'>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf_serialize_example(f0, f1, f2, f3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CrFZ9avE3HUF"
   },
   "source": [
    "将此函数应用于数据集中的每个元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.681378Z",
     "iopub.status.busy": "2023-11-07T23:58:50.680756Z",
     "iopub.status.idle": "2023-11-07T23:58:50.727893Z",
     "shell.execute_reply": "2023-11-07T23:58:50.727146Z"
    },
    "id": "VDeqYVbW3ww9"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<_MapDataset element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "serialized_features_dataset = features_dataset.map(tf_serialize_example)\n",
    "serialized_features_dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.731777Z",
     "iopub.status.busy": "2023-11-07T23:58:50.731199Z",
     "iopub.status.idle": "2023-11-07T23:58:50.734797Z",
     "shell.execute_reply": "2023-11-07T23:58:50.734144Z"
    },
    "id": "DlDfuh46bRf6"
   },
   "outputs": [],
   "source": [
    "def generator():\n",
    "  for features in features_dataset:\n",
    "    yield serialize_example(*features)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.738208Z",
     "iopub.status.busy": "2023-11-07T23:58:50.737942Z",
     "iopub.status.idle": "2023-11-07T23:58:50.765659Z",
     "shell.execute_reply": "2023-11-07T23:58:50.764912Z"
    },
    "id": "iv9oXKrcbhvX"
   },
   "outputs": [],
   "source": [
    "serialized_features_dataset = tf.data.Dataset.from_generator(\n",
    "    generator, output_types=tf.string, output_shapes=())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.770103Z",
     "iopub.status.busy": "2023-11-07T23:58:50.769350Z",
     "iopub.status.idle": "2023-11-07T23:58:50.774353Z",
     "shell.execute_reply": "2023-11-07T23:58:50.773688Z"
    },
    "id": "Dqz8C4D5cIj9"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<_FlatMapDataset element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "serialized_features_dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "p6lw5VYpjZZC"
   },
   "source": [
    "并将它们写入 TFRecord 文件："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:50.778164Z",
     "iopub.status.busy": "2023-11-07T23:58:50.777578Z",
     "iopub.status.idle": "2023-11-07T23:58:56.079896Z",
     "shell.execute_reply": "2023-11-07T23:58:56.079022Z"
    },
    "id": "vP1VgTO44UIE"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /tmpfs/tmp/ipykernel_587965/3575438268.py:2: TFRecordWriter.__init__ (from tensorflow.python.data.experimental.ops.writers) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "To write TFRecords to disk, use `tf.io.TFRecordWriter`. To save and load the contents of a dataset, use `tf.data.experimental.save` and `tf.data.experimental.load`\n"
     ]
    }
   ],
   "source": [
    "filename = 'test.tfrecord'\n",
    "writer = tf.data.experimental.TFRecordWriter(filename)\n",
    "writer.write(serialized_features_dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6aV0GQhV8tmp"
   },
   "source": [
    "### 读取 TFRecord 文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "o3J5D4gcSy8N"
   },
   "source": [
    "您还可以使用 `tf.data.TFRecordDataset` 类来读取 TFRecord 文件。\n",
    "\n",
    "有关通过 `tf.data` 使用 TFRecord 文件的详细信息，请参见[此处](https://tensorflow.google.cn/guide/datasets#consuming_tfrecord_data)。\n",
    "\n",
    "使用 `TFRecordDataset` 对于标准化输入数据和优化性能十分有用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.084572Z",
     "iopub.status.busy": "2023-11-07T23:58:56.083958Z",
     "iopub.status.idle": "2023-11-07T23:58:56.099649Z",
     "shell.execute_reply": "2023-11-07T23:58:56.098981Z"
    },
    "id": "6OjX6UZl-bHC"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<TFRecordDatasetV2 element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "filenames = [filename]\n",
    "raw_dataset = tf.data.TFRecordDataset(filenames)\n",
    "raw_dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6_EQ9i2E_-Fz"
   },
   "source": [
    "此时，数据集包含序列化的 `tf.train.Example` 消息。迭代时，它会将其作为标量字符串张量返回。\n",
    "\n",
    "使用 `.take` 方法仅显示前 10 条记录。\n",
    "\n",
    "注：在 `tf.data.Dataset` 上进行迭代仅在启用了 Eager Execution 时有效。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.103381Z",
     "iopub.status.busy": "2023-11-07T23:58:56.102809Z",
     "iopub.status.idle": "2023-11-07T23:58:56.132128Z",
     "shell.execute_reply": "2023-11-07T23:58:56.131305Z"
    },
    "id": "hxVXpLz_AJlm"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nQ\\n\\x13\\n\\x08feature2\\x12\\x07\\n\\x05\\n\\x03dog\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x01\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\x11\\x02:?\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nS\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x01\\n\\x15\\n\\x08feature2\\x12\\t\\n\\x07\\n\\x05horse\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x03\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\xa0E\\xf0\\xbd'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nR\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x04\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x044L\\xa4>\\n\\x14\\n\\x08feature2\\x12\\x08\\n\\x06\\n\\x04goat'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nQ\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\xc0\\xd8\\x82?\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x01\\n\\x13\\n\\x08feature2\\x12\\x07\\n\\x05\\n\\x03cat'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nS\\n\\x15\\n\\x08feature2\\x12\\t\\n\\x07\\n\\x05horse\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\xacH3?\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x03'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nS\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x03\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04g(\\x08?\\n\\x15\\n\\x08feature2\\x12\\t\\n\\x07\\n\\x05horse'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nR\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\xb3[\\x1a\\xbf\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x04\\n\\x14\\n\\x08feature2\\x12\\x08\\n\\x06\\n\\x04goat\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x01'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nS\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x03\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\xcd\\xa0}=\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x15\\n\\x08feature2\\x12\\t\\n\\x07\\n\\x05horse'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nQ\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04\\x0e=L?\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x00\\n\\x13\\n\\x08feature2\\x12\\x07\\n\\x05\\n\\x03cat'>\n",
      "<tf.Tensor: shape=(), dtype=string, numpy=b'\\nS\\n\\x15\\n\\x08feature2\\x12\\t\\n\\x07\\n\\x05horse\\n\\x11\\n\\x08feature0\\x12\\x05\\x1a\\x03\\n\\x01\\x01\\n\\x14\\n\\x08feature3\\x12\\x08\\x12\\x06\\n\\x04KV\\xf4\\xbe\\n\\x11\\n\\x08feature1\\x12\\x05\\x1a\\x03\\n\\x01\\x03'>\n"
     ]
    }
   ],
   "source": [
    "for raw_record in raw_dataset.take(10):\n",
    "  print(repr(raw_record))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "W-6oNzM4luFQ"
   },
   "source": [
    "可以使用以下函数对这些张量进行解析。请注意，这里的 `feature_description` 是必需的，因为数据集使用计算图执行，并且需要以下描述来构建它们的形状和类型签名："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.135815Z",
     "iopub.status.busy": "2023-11-07T23:58:56.135230Z",
     "iopub.status.idle": "2023-11-07T23:58:56.140281Z",
     "shell.execute_reply": "2023-11-07T23:58:56.139567Z"
    },
    "id": "zQjbIR1nleiy"
   },
   "outputs": [],
   "source": [
    "# Create a description of the features.\n",
    "feature_description = {\n",
    "    'feature0': tf.io.FixedLenFeature([], tf.int64, default_value=0),\n",
    "    'feature1': tf.io.FixedLenFeature([], tf.int64, default_value=0),\n",
    "    'feature2': tf.io.FixedLenFeature([], tf.string, default_value=''),\n",
    "    'feature3': tf.io.FixedLenFeature([], tf.float32, default_value=0.0),\n",
    "}\n",
    "\n",
    "def _parse_function(example_proto):\n",
    "  # Parse the input `tf.train.Example` proto using the dictionary above.\n",
    "  return tf.io.parse_single_example(example_proto, feature_description)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "gWETjUqhEQZf"
   },
   "source": [
    "或者，使用 `tf.parse example` 一次解析整个批次。使用 `tf.data.Dataset.map` 方法将此函数应用于数据集中的每一项："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.143701Z",
     "iopub.status.busy": "2023-11-07T23:58:56.143167Z",
     "iopub.status.idle": "2023-11-07T23:58:56.186883Z",
     "shell.execute_reply": "2023-11-07T23:58:56.186057Z"
    },
    "id": "6Ob7D-zmBm1w"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<_MapDataset element_spec={'feature0': TensorSpec(shape=(), dtype=tf.int64, name=None), 'feature1': TensorSpec(shape=(), dtype=tf.int64, name=None), 'feature2': TensorSpec(shape=(), dtype=tf.string, name=None), 'feature3': TensorSpec(shape=(), dtype=tf.float32, name=None)}>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "parsed_dataset = raw_dataset.map(_parse_function)\n",
    "parsed_dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "sNV-XclGnOvn"
   },
   "source": [
    "使用 Eager Execution 在数据集中显示观测值。此数据集中有 10,000 个观测值，但只会显示前 10 个。数据会作为特征字典进行显示。每一项都是一个 `tf.Tensor`，此张量的 `numpy` 元素会显示特征的值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.190708Z",
     "iopub.status.busy": "2023-11-07T23:58:56.190065Z",
     "iopub.status.idle": "2023-11-07T23:58:56.238235Z",
     "shell.execute_reply": "2023-11-07T23:58:56.237254Z"
    },
    "id": "x2LT2JCqhoD_"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'dog'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.72659403>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.1173203>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.32089388>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.0222397>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.70032763>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.5318665>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.6029617>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.06192093>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.7978066>}\n",
      "{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.47722086>}\n"
     ]
    }
   ],
   "source": [
    "for parsed_record in parsed_dataset.take(10):\n",
    "  print(repr(parsed_record))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Cig9EodTlDmg"
   },
   "source": [
    "在这里，`tf.parse_example` 函数会将 `tf.Example` 字段解压缩为标准张量。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jyg1g3gU7DNn"
   },
   "source": [
    "## Python 中的 TFRecord 文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3FXG3miA7Kf1"
   },
   "source": [
    "`tf.io` 模块还包含用于读取和写入 TFRecord 文件的纯 Python 函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CKn5uql2lAaN"
   },
   "source": [
    "### 写入 TFRecord 文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "LNW_FA-GQWXs"
   },
   "source": [
    "接下来，将 10,000 个观测值写入文件 `test.tfrecord`。每个观测值都将转换为一条 `tf.Example` 消息，然后被写入文件。随后，您可以验证是否已创建 `test.tfrecord` 文件："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.242605Z",
     "iopub.status.busy": "2023-11-07T23:58:56.242062Z",
     "iopub.status.idle": "2023-11-07T23:58:56.743702Z",
     "shell.execute_reply": "2023-11-07T23:58:56.742519Z"
    },
    "id": "MKPHzoGv7q44"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmpfs/tmp/ipykernel_587965/1733628823.py:16: DeprecationWarning: In future, it will be an error for 'np.bool_' scalars to be interpreted as an index\n",
      "  return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))\n"
     ]
    }
   ],
   "source": [
    "# Write the `tf.train.Example` observations to the file.\n",
    "with tf.io.TFRecordWriter(filename) as writer:\n",
    "  for i in range(n_observations):\n",
    "    example = serialize_example(feature0[i], feature1[i], feature2[i], feature3[i])\n",
    "    writer.write(example)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.748682Z",
     "iopub.status.busy": "2023-11-07T23:58:56.747862Z",
     "iopub.status.idle": "2023-11-07T23:58:56.907292Z",
     "shell.execute_reply": "2023-11-07T23:58:56.905791Z"
    },
    "id": "EjdFHHJMpUUo"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "984K\ttest.tfrecord\r\n"
     ]
    }
   ],
   "source": [
    "!du -sh {filename}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2osVRnYNni-E"
   },
   "source": [
    "### 读取 TFRecord 文件\n",
    "\n",
    "您可以使用 `tf.train.Example.ParseFromString` 轻松解析以下序列化张量："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.912378Z",
     "iopub.status.busy": "2023-11-07T23:58:56.912010Z",
     "iopub.status.idle": "2023-11-07T23:58:56.932300Z",
     "shell.execute_reply": "2023-11-07T23:58:56.931302Z"
    },
    "id": "U3tnd3LerOtV"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<TFRecordDatasetV2 element_spec=TensorSpec(shape=(), dtype=tf.string, name=None)>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "filenames = [filename]\n",
    "raw_dataset = tf.data.TFRecordDataset(filenames)\n",
    "raw_dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.935729Z",
     "iopub.status.busy": "2023-11-07T23:58:56.935461Z",
     "iopub.status.idle": "2023-11-07T23:58:56.962507Z",
     "shell.execute_reply": "2023-11-07T23:58:56.961748Z"
    },
    "id": "nsEAACHcnm3f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "features {\n",
      "  feature {\n",
      "    key: \"feature0\"\n",
      "    value {\n",
      "      int64_list {\n",
      "        value: 0\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "  feature {\n",
      "    key: \"feature1\"\n",
      "    value {\n",
      "      int64_list {\n",
      "        value: 1\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "  feature {\n",
      "    key: \"feature2\"\n",
      "    value {\n",
      "      bytes_list {\n",
      "        value: \"dog\"\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "  feature {\n",
      "    key: \"feature3\"\n",
      "    value {\n",
      "      float_list {\n",
      "        value: 0.7265940308570862\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for raw_record in raw_dataset.take(1):\n",
    "  example = tf.train.Example()\n",
    "  example.ParseFromString(raw_record.numpy())\n",
    "  print(example)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "yhnZZmhm1miG"
   },
   "source": [
    "这将返回 `tf.train.Example` proto，它难以按照原样使用，但基本上可以表示：\n",
    "\n",
    "```\n",
    "Dict[str,\n",
    "     Union[List[float],\n",
    "           List[int],\n",
    "           List[str]]]\n",
    "```\n",
    "\n",
    "以下代码可以手动将 `Example` 转换成 NumPy 数组的字典，无需使用 TensorFlow Ops。有关详情，请参阅 [PROTO 文件](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/example/feature.proto)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.966542Z",
     "iopub.status.busy": "2023-11-07T23:58:56.965855Z",
     "iopub.status.idle": "2023-11-07T23:58:56.972690Z",
     "shell.execute_reply": "2023-11-07T23:58:56.971988Z"
    },
    "id": "Ziv9tiNE1l6J"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'feature3': array([0.72659403]),\n",
       " 'feature1': array([1]),\n",
       " 'feature0': array([0]),\n",
       " 'feature2': array([b'dog'], dtype='|S3')}"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = {}\n",
    "# example.features.feature is the dictionary\n",
    "for key, feature in example.features.feature.items():\n",
    "  # The values are the Feature objects which contain a `kind` which contains:\n",
    "  # one of three fields: bytes_list, float_list, int64_list\n",
    "\n",
    "  kind = feature.WhichOneof('kind')\n",
    "  result[key] = np.array(getattr(feature, kind).value)\n",
    "\n",
    "result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "S0tFDrwdoj3q"
   },
   "source": [
    "## 演练：读取和写入图像数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rjN2LFxFpcR9"
   },
   "source": [
    "下面是关于如何使用 TFRecord 读取和写入图像数据的端到端示例。您将使用图像作为输入数据，将数据写入 TFRecord 文件，然后将文件读取回来并显示图像。\n",
    "\n",
    "如果您想在同一个输入数据集上使用多个模型，这种做法会很有用。您可以不以原始格式存储图像，而是将图像预处理为 TFRecord 格式，然后将其用于所有后续的处理和建模中。\n",
    "\n",
    "首先，让我们下载雪中的猫的[图像](https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg)，以及施工中的纽约威廉斯堡大桥的[照片](https://upload.wikimedia.org/wikipedia/commons/f/fe/New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg)。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5Lk2qrKvN0yu"
   },
   "source": [
    "### 提取图像"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:56.976371Z",
     "iopub.status.busy": "2023-11-07T23:58:56.976094Z",
     "iopub.status.idle": "2023-11-07T23:58:57.153663Z",
     "shell.execute_reply": "2023-11-07T23:58:57.152957Z"
    },
    "id": "3a0fmwg8lHdF"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/320px-Felis_catus-cat_on_snow.jpg\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      " 8192/17858 [============>.................] - ETA: 0s"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
      "17858/17858 [==============================] - 0s 0us/step\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\r",
      " 8192/15477 [==============>...............] - ETA: 0s"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
      "15477/15477 [==============================] - 0s 0us/step\n"
     ]
    }
   ],
   "source": [
    "cat_in_snow  = tf.keras.utils.get_file(\n",
    "    '320px-Felis_catus-cat_on_snow.jpg',\n",
    "    'https://storage.googleapis.com/download.tensorflow.org/example_images/320px-Felis_catus-cat_on_snow.jpg')\n",
    "\n",
    "williamsburg_bridge = tf.keras.utils.get_file(\n",
    "    '194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg',\n",
    "    'https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.157284Z",
     "iopub.status.busy": "2023-11-07T23:58:57.157005Z",
     "iopub.status.idle": "2023-11-07T23:58:57.164136Z",
     "shell.execute_reply": "2023-11-07T23:58:57.163438Z"
    },
    "id": "7aJJh7vENeE4"
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "Image cc-by: <a \"href=https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg\">Von.grzanka</a>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display.display(display.Image(filename=cat_in_snow))\n",
    "display.display(display.HTML('Image cc-by: <a \"href=https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg\">Von.grzanka</a>'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.167804Z",
     "iopub.status.busy": "2023-11-07T23:58:57.167151Z",
     "iopub.status.idle": "2023-11-07T23:58:57.173642Z",
     "shell.execute_reply": "2023-11-07T23:58:57.173009Z"
    },
    "id": "KkW0uuhcXZqA"
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<a \"href=https://commons.wikimedia.org/wiki/File:New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg\">From Wikimedia</a>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display.display(display.Image(filename=williamsburg_bridge))\n",
    "display.display(display.HTML('<a \"href=https://commons.wikimedia.org/wiki/File:New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg\">From Wikimedia</a>'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "VSOgJSwoN5TQ"
   },
   "source": [
    "### 写入 TFRecord 文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Azx83ryQEU6T"
   },
   "source": [
    "和以前一样，将特征编码为与 `tf.Example` 兼容的类型。这将存储原始图像字符串特征，以及高度、宽度、深度和任意 `label` 特征。后者会在您写入文件以区分猫和桥的图像时使用。将 `0` 用于猫的图像，将 `1` 用于桥的图像："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.177210Z",
     "iopub.status.busy": "2023-11-07T23:58:57.176944Z",
     "iopub.status.idle": "2023-11-07T23:58:57.180455Z",
     "shell.execute_reply": "2023-11-07T23:58:57.179771Z"
    },
    "id": "kC4TS1ZEONHr"
   },
   "outputs": [],
   "source": [
    "image_labels = {\n",
    "    cat_in_snow : 0,\n",
    "    williamsburg_bridge : 1,\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.183721Z",
     "iopub.status.busy": "2023-11-07T23:58:57.183298Z",
     "iopub.status.idle": "2023-11-07T23:58:57.192744Z",
     "shell.execute_reply": "2023-11-07T23:58:57.192006Z"
    },
    "id": "c5njMSYNEhNZ"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "features {\n",
      "  feature {\n",
      "    key: \"depth\"\n",
      "    value {\n",
      "      int64_list {\n",
      "        value: 3\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "  feature {\n",
      "    key: \"height\"\n",
      "    value {\n",
      "      int64_list {\n",
      "        value: 213\n",
      "      }\n",
      "...\n"
     ]
    }
   ],
   "source": [
    "# This is an example, just using the cat image.\n",
    "image_string = open(cat_in_snow, 'rb').read()\n",
    "\n",
    "label = image_labels[cat_in_snow]\n",
    "\n",
    "# Create a dictionary with features that may be relevant.\n",
    "def image_example(image_string, label):\n",
    "  image_shape = tf.io.decode_jpeg(image_string).shape\n",
    "\n",
    "  feature = {\n",
    "      'height': _int64_feature(image_shape[0]),\n",
    "      'width': _int64_feature(image_shape[1]),\n",
    "      'depth': _int64_feature(image_shape[2]),\n",
    "      'label': _int64_feature(label),\n",
    "      'image_raw': _bytes_feature(image_string),\n",
    "  }\n",
    "\n",
    "  return tf.train.Example(features=tf.train.Features(feature=feature))\n",
    "\n",
    "for line in str(image_example(image_string, label)).split('\\n')[:15]:\n",
    "  print(line)\n",
    "print('...')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2G_o3O9MN0Qx"
   },
   "source": [
    "请注意，所有特征现在都存储在 `tf.Example` 消息中。接下来，函数化上面的代码，并将示例消息写入名为 `images.tfrecords` 的文件："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.196427Z",
     "iopub.status.busy": "2023-11-07T23:58:57.195976Z",
     "iopub.status.idle": "2023-11-07T23:58:57.202662Z",
     "shell.execute_reply": "2023-11-07T23:58:57.202004Z"
    },
    "id": "qcw06lQCOCZU"
   },
   "outputs": [],
   "source": [
    "# Write the raw image files to `images.tfrecords`.\n",
    "# First, process the two images into `tf.train.Example` messages.\n",
    "# Then, write to a `.tfrecords` file.\n",
    "record_file = 'images.tfrecords'\n",
    "with tf.io.TFRecordWriter(record_file) as writer:\n",
    "  for filename, label in image_labels.items():\n",
    "    image_string = open(filename, 'rb').read()\n",
    "    tf_example = image_example(image_string, label)\n",
    "    writer.write(tf_example.SerializeToString())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.205914Z",
     "iopub.status.busy": "2023-11-07T23:58:57.205652Z",
     "iopub.status.idle": "2023-11-07T23:58:57.357266Z",
     "shell.execute_reply": "2023-11-07T23:58:57.356262Z"
    },
    "id": "yJrTe6tHPCfs"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "36K\timages.tfrecords\r\n"
     ]
    }
   ],
   "source": [
    "!du -sh {record_file}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jJSsCkZLPH6K"
   },
   "source": [
    "### 读取 TFRecord 文件\n",
    "\n",
    "现在，您有文件 `images.tfrecords`，并可以迭代其中的记录以将您写入的内容读取回来。因为在此示例中您只需重新生成图像，所以您只需要原始图像字符串这一个特征。使用上面描述的 getter 方法（即 `example.features.feature['image_raw'].bytes_list.value[0]`）提取该特征。您还可以使用标签来确定哪个记录是猫，哪个记录是桥："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.361939Z",
     "iopub.status.busy": "2023-11-07T23:58:57.361627Z",
     "iopub.status.idle": "2023-11-07T23:58:57.425588Z",
     "shell.execute_reply": "2023-11-07T23:58:57.424883Z"
    },
    "id": "M6Cnfd3cTKHN"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<_MapDataset element_spec={'depth': TensorSpec(shape=(), dtype=tf.int64, name=None), 'height': TensorSpec(shape=(), dtype=tf.int64, name=None), 'image_raw': TensorSpec(shape=(), dtype=tf.string, name=None), 'label': TensorSpec(shape=(), dtype=tf.int64, name=None), 'width': TensorSpec(shape=(), dtype=tf.int64, name=None)}>"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "raw_image_dataset = tf.data.TFRecordDataset('images.tfrecords')\n",
    "\n",
    "# Create a dictionary describing the features.\n",
    "image_feature_description = {\n",
    "    'height': tf.io.FixedLenFeature([], tf.int64),\n",
    "    'width': tf.io.FixedLenFeature([], tf.int64),\n",
    "    'depth': tf.io.FixedLenFeature([], tf.int64),\n",
    "    'label': tf.io.FixedLenFeature([], tf.int64),\n",
    "    'image_raw': tf.io.FixedLenFeature([], tf.string),\n",
    "}\n",
    "\n",
    "def _parse_image_function(example_proto):\n",
    "  # Parse the input tf.train.Example proto using the dictionary above.\n",
    "  return tf.io.parse_single_example(example_proto, image_feature_description)\n",
    "\n",
    "parsed_image_dataset = raw_image_dataset.map(_parse_image_function)\n",
    "parsed_image_dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "0PEEFPk4NEg1"
   },
   "source": [
    "从 TFRecord 文件中恢复图像："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-11-07T23:58:57.429249Z",
     "iopub.status.busy": "2023-11-07T23:58:57.428978Z",
     "iopub.status.idle": "2023-11-07T23:58:57.475130Z",
     "shell.execute_reply": "2023-11-07T23:58:57.474425Z"
    },
    "id": "yZf8jOyEIjSF"
   },
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for image_features in parsed_image_dataset:\n",
    "  image_raw = image_features['image_raw'].numpy()\n",
    "  display.display(display.Image(data=image_raw))"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [
    "pL--_KGdYoBz"
   ],
   "name": "tfrecord.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
